/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package project1;

import java.util.HashMap;

/**
 *
 * @author rr
 */
public class Solver {

    private int[] solution = null;
    int n = SetUp.getInstance().getLengthOfSchedule() * SetUp.getInstance().getNumberOfEmployees();

    public Solver() {
    }

    public void solve() {

        int[] tempAssignment = new int[n];
        for (int i = 0; i < n; i++) {
            tempAssignment[i] = -1;
        }


        boolean[][] allOnes = new boolean[SetUp.getInstance().getNumberOfShifts() + 1][SetUp.getInstance().getNumberOfEmployees() * SetUp.getInstance().getLengthOfSchedule()];

        for (int i = 0; i < allOnes.length; ++i) {
            for (int j = 0; j < allOnes[0].length; ++j) {
                allOnes[i][j] = true;
            }
        }



        int firstVariable = ConstraintChecker.getInstance().updatePossibleAssignments(allOnes, tempAssignment)[0];


        for (int i = 0; i < SetUp.getInstance().getNames().length; ++i) {
            if (this.solution != null) {
                break;
            }

            if (allOnes[i][firstVariable]) {
                CandidateSolution firstTry = new CandidateSolution(tempAssignment, allOnes);
                firstTry.setNextVariableIndex(firstVariable);
                this.traverse(firstTry);
            }
        }
    }

    private void traverse(CandidateSolution thisSolution) {
        int n = SetUp.getInstance().getLengthOfSchedule() * SetUp.getInstance().getNumberOfEmployees();

        CandidateSolution[] solutions = new CandidateSolution[SetUp.getInstance().getNames().length];
        
        for(int i = 0; i<SetUp.getInstance().getNames().length; ++i){
            
            if(this.solution != null){
                return;
            }
            
            if(thisSolution.getPossibleAssignments()[i][thisSolution.getNextVariableIndex()] == true){
                solutions[i] = thisSolution.assignNext(i);

                //Run.printWorkSchedule(newSolution.getTempAssignments());
                
                if (solutions[i].getNumberOfAssignedValues() == n) {
                    this.solution = solutions[i].getTempAssignments();
                    return;
                }                  
                
            }
        }
        
        sort(solutions);
        
        for(int i = 0; i<SetUp.getInstance().getNames().length; ++i){
            if(this.solution != null){
                return;
            }
            
            if(solutions[i]!=null){
                if (solutions[i].getNumberOfAssignedValues() == n) {
                    this.solution = solutions[i].getTempAssignments();
                    return;
                } 
                if (solutions[i].getNextVariableIndex() != -1) {
                    Run.printWorkSchedule(solutions[i].getTempAssignments());
                    this.traverse(solutions[i]);
                }
            }
        }
            
        
    }
    
    
    

    public int[] getSolution() {
        return solution;
    }

    private void sort(CandidateSolution[] solutions) {
        for (int i = 0; i < solutions.length; i++) {
            for (int j = i + 1; j < solutions.length; j++) {
                if (solutions[i] != null && solutions[j] != null && solutions[i].getMinimumDomainSize() < solutions[j].getMinimumDomainSize()) {
                    CandidateSolution h = solutions[i];
                    solutions[i] = solutions[j];
                    solutions[j] = h;
                }
            }
        }
    }
}
